package com.dl.debugtools

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.BitmapFactory
import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.util.Log
import android.widget.Toast
import androidx.core.content.FileProvider
import androidx.lifecycle.LifecycleService
import androidx.lifecycle.lifecycleScope
import com.dl.base.AppContext
import com.dl.base.appContext
import com.dl.base.utils.AutoInstallUtil
import com.dl.debugtools.api.DebugToolsRepository
import io.reactivex.rxjava3.schedulers.Schedulers
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import java.io.*


class CommandService : LifecycleService() {
    private val api = DebugToolsRepository.instance
    private val commandChannel = Channel<String>()
    private val commandResultChannel = Channel<String>()
    private var commandScope: CoroutineScope? = null
    private var isStart = false

    override fun onCreate() {
        super.onCreate()
        startNotificationForeground()
        lifecycleScope.launch {
            api.generateDevice()?.let {
                DebugToolsPreferences.deviceName = it.name ?: ""
                api.loadUrl(it.id)
                subscribeCommand()
                subscribeInstall()
            }
        }
        lifecycleScope.launch {
            while (isActive) {
                val comm = commandChannel.receive()
                withContext(Dispatchers.IO) {
                    runComm(comm)
                }
            }
        }
        lifecycleScope.launch {
            while (isActive) {
                val result = commandResultChannel.receive()
                api.sendCommandResult(result)
            }
        }

        lifecycleScope.launch {

        }
    }

    private fun subscribeCommand() {
        lifecycleScope.launch {
            api.subscribeCommand()
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .subscribe({
                    lifecycleScope.launch {
                        if (it.stringMsg == "start") {
                            isReadLog = true
                            if (!isStart) {
                                initLog()
                                isStart = true
                            }
                        } else if (it.stringMsg == "end") {
                            isReadLog = false
                            isStart = false
                            commandScope?.cancel()
                        }
                    }
                }, {})
        }
    }

    private fun subscribeInstall() {
        lifecycleScope.launch {
            api.subscribeInstall()
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .subscribe({
                    lifecycleScope.launch {
                        if (it.stringMsg == "install") {
                            try {
                                api.downloadFile(
                                    FileUtil.getDownloadInstallPath(),
                                    AppContext.url + "/resources/getInstallApk/"
                                )
                            } catch (e: Exception) {
                                e.printStackTrace()
                            }
                            try {
                                if (!AutoInstallUtil.install(FileUtil.getDownloadInstallPath())) {
                                    notifyInstall()
                                } else {
                                    notifySuccess()
                                }
                            } catch (e: Exception) {
                                notifyInstall()
                            }
                        }
                    }
                }, {})
        }
    }

    private fun runComm(command: String) {
        try {
            val process = Runtime.getRuntime().exec(command)
            lifecycleScope.launch {
                val reader = process.inputStream.bufferedReader()
                withContext(Dispatchers.IO) {
                    while (true) {
                        val text: String? = reader.readLine()
                        if (text != null) {
                            lifecycleScope.launch { commandResultChannel.send(text) }
                        }
                    }
                }
            }
        } catch (e: Exception) {
            StringWriter().use { sw ->
                PrintWriter(sw).use { pw ->
                    e.printStackTrace(pw)
                    val error = sw.toString()
                    lifecycleScope.launch { commandResultChannel.send(error) }
                }
            }
        }
    }

    private var isReadLog = false
    private fun initLog() {
        commandScope = CoroutineScope(Dispatchers.IO)
        commandScope!!.launch {
            withContext(Dispatchers.IO) {
                Runtime.getRuntime().exec("chmod 04755 /system/bin/logcat").waitFor()
                Runtime.getRuntime().exec("logcat -c").waitFor()
                val process = Runtime.getRuntime().exec("logcat")

                while (isReadLog) {
                    val reader = process.inputStream.bufferedReader()
                    var text: String? = null
                    while (reader.readLine()?.also { text = it } != null) {
                        api.sendCommandResult(text!!)
                    }
                }
            }
        }
    }

    private fun startNotificationForeground() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channelId = "DebugTools-pro"
            val manager: NotificationManager =
                getSystemService(NOTIFICATION_SERVICE) as NotificationManager
            val channel =
                NotificationChannel(
                    channelId,
                    "DebugTools-pro",
                    NotificationManager.IMPORTANCE_HIGH
                )
            channel.enableLights(true) //设置提示灯
            channel.lightColor = Color.GREEN //设置提示灯颜色
            channel.setShowBadge(true) //显示logo
            channel.description = "DebugTools-pro" //设置描述
            channel.lockscreenVisibility =
                Notification.VISIBILITY_PUBLIC //设置锁屏可见 VISIBILITY_PUBLIC=可见
            manager.createNotificationChannel(channel)
            val notification = Notification.Builder(this, channelId)
                .setAutoCancel(false)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))
                .setContentTitle("DebugTools-pro") //标题
                .setWhen(System.currentTimeMillis())
                .build()
            startForeground(
                1,
                notification
            )
        }
    }

    private fun notifySuccess() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val context = applicationContext
            val channelId = "message" // 通知渠道

            val notification: Notification = Notification.Builder(context)
                .setChannelId(channelId)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))
                .setDefaults(Notification.DEFAULT_SOUND)
                .setContentTitle("软件更新完成")
                .build()
            val notificationManager = context
                .getSystemService(NOTIFICATION_SERVICE) as NotificationManager
            val channel = NotificationChannel(
                channelId,
                "message",
                NotificationManager.IMPORTANCE_DEFAULT
            )
            notificationManager.createNotificationChannel(channel)
            notificationManager.notify(4, notification)
        } else {
            val notification: Notification = Notification.Builder(this)
                .setContentTitle("软件更新完成")
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))
                .setDefaults(Notification.DEFAULT_SOUND)
                .build()
            (appContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).notify(
                4,
                notification
            )
        }
    }

    private fun notifyInstall() {
        val apkFile = File(FileUtil.getDownloadInstallPath())
        val installIntent = Intent(Intent.ACTION_VIEW)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            installIntent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
            val uri = FileProvider.getUriForFile(this, "${packageName}.fileprovider", apkFile)
            installIntent.setDataAndType(uri, "application/vnd.android.package-archive")
        } else {
            installIntent.setDataAndType(
                Uri.fromFile(apkFile),
                "application/vnd.android.package-archive"
            )
        }

        val pendingIntent = PendingIntent.getActivity(appContext, 0, installIntent, 0)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val context = applicationContext
            val channelId = "install" // 通知渠道

            val notification: Notification = Notification.Builder(context)
                .setChannelId(channelId)
                .setContentIntent(pendingIntent)
                .setDefaults(Notification.DEFAULT_SOUND)
                .setContentTitle("软件已更新，点击安装")
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))
                .build()
            val notificationManager = context
                .getSystemService(NOTIFICATION_SERVICE) as NotificationManager
            val channel = NotificationChannel(
                channelId,
                "install",
                NotificationManager.IMPORTANCE_DEFAULT
            )
            notificationManager.createNotificationChannel(channel)
            notificationManager.notify(3, notification)
        } else {
            val notification: Notification = Notification.Builder(this)
                .setContentTitle("软件已更新，点击安装")
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))
                .setContentIntent(pendingIntent)
                .setDefaults(Notification.DEFAULT_SOUND)
                .build()

            (appContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).notify(
                3,
                notification
            )
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        commandScope?.cancel()
    }
}